/**
 * This file is part of Opintopaivakirja.
 *
 * Opintopaivakirja is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Opintopaivakirja is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Opintopaivakirja.  If not, see <http://www.gnu.org/licenses/>.
 */
package opintopaivakirja;

import java.sql.Connection;
import java.sql.Timestamp;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

/**
 * Luokka toteuttaa järjestelmään projekteihin liittyvät ominaisuudet.
 * Projekti sisältää tavallisesti n-määrä muistiipanoja.
 * 
 * @author Teemu Jonkkari
 * @version 1.0
 */
public class Projekti {

    private int id;
    private int isa;
    private int tila;
    private int arvosana;
    private int arvosana_oma;
    private int asema;
    private String nimi;
    private String esittely;
    private String arviointi;
    private String linkki;
    private Date pvm_alku;
    private Date pvm_loppu;
    private Timestamp pvm_paivitetty;
    private ArrayList<Muistiinpano> muistiinpanot;
    private ArrayList<Projekti> lapsiprojektit;

    /**
     * Oletusmuodostin
     */
    public Projekti() {
        this.id = 0;
        this.isa = 0;
        this.tila = 0;
        this.muistiinpanot = new ArrayList<Muistiinpano>();
        this.lapsiprojektit = new ArrayList<Projekti>();
    }

    /**
     * Muodostin, jolla voidaan asettaa suoraan uuden projekti parametrit.
     *<p>
     * Tila kertoo projektista onko se
     *<ul>
     * <li>Uusi (0)
     * <li>Vanha (1)
     * <li>Poistettava (-1)
     *</ul>
     * Asema kertoo projektista onko se
     *<ul>
     * <li>Tavallinen (0)
     * <li>Valmis (1)
     * <li>Poistettu (2)
     *</ul>
     * 
     * @param nimi Projektin nimi.
     * @param esittely Projektin esittelyteksti.
     * @param arviointi Projektin loppuarviointi.
     * @param linkki Projektin kotisivu.
     * @param arvosana Projektista saatu ulkoinen arvosana.
     * @param arvosana_oma Projektille annettu oma arvosana.
     * @param asema Asema kertoo onko prjekti käynnissä (0), valmis (1) vai poistettu (2).
     * @param isa Projektin id-tunniste, jonka alla alaprojektina kyseinen Projekti sijaitsee.
     * @param pvm_alku Päivämäärä, jolloin projekti alkoi.
     * @param pvm_loppu Päivämäärä, jolloin projekti loppui.
     */
    public Projekti(String nimi, String esittely, String arviointi,
            String linkki, int arvosana, int arvosana_oma, int isa,
            int asema, Date pvm_alku, Date pvm_loppu) {
        this.nimi = nimi;
        this.esittely = esittely;
        this.arviointi = arviointi;
        this.linkki = linkki;
        this.arvosana = arvosana;
        this.arvosana_oma = arvosana_oma;
        this.isa = isa;
        this.asema = asema;
        this.pvm_alku = pvm_alku;
        this.pvm_loppu = pvm_loppu;

        this.id = 0;
        this.tila = 0;
        this.muistiinpanot = new ArrayList<Muistiinpano>();
        this.lapsiprojektit = new ArrayList<Projekti>();
    }

    /**
     * Muodostin, jolla voidaan asettaa suoraan kaikki projekti parametrit.
     *<p>
     * Tarkoitettu tietokantakyselyn käytettäväksi, sillä tällöin tiedetään myös id ja voidaan asettaa se.
     * Käyttäjän tekemällä uudella projektilla ei ole id:tä ennen sen kantaan tallentamista.
     *
     * @param id Projektin id-tunniste.
     * @param nimi Projektin nimi.
     * @param esittely Projektin esittelyteksti.
     * @param linkki Projektin kotisivu.
     * @param arvosana Projektista saatu ulkoinen arvosana.
     * @param arvosana_oma Projektille annettu oma arvosana.
     * @param asema Asema kertoo onko prjekti käynnissä (0), valmis (1) vai poistettu (2).
     * @param isa Projektin id-tunniste, jonka alla alaprojektina kyseinen Projekti sijaitsee.
     * @param pvm_alku Päivämäärä, jolloin projekti alkoi.
     * @param pvm_loppu Päivämäärä, jolloin projekti loppui.
     * @param pvm_paivitetty Aikaleima, jolloin projektia on päivitetty.
     * @param tila Projetin tila olioon merkittynä: uusi (0), vanha (1), poistettava (-1).
     */
    private Projekti(int id, String nimi, String esittely,
            String arviointi, String linkki, int arvosana, int arvosana_oma,
            int asema, int isa, Date pvm_alku, Date pvm_loppu,
            Timestamp pvm_paivitetty, int tila) {
        this.id = id;
        this.nimi = nimi;
        this.esittely = esittely;
        this.arviointi = arviointi;
        this.linkki = linkki;
        this.arvosana = arvosana;
        this.arvosana_oma = arvosana_oma;
        this.isa = isa;
        this.tila = tila;
        this.asema = asema;
        this.pvm_alku = pvm_alku;
        this.pvm_loppu = pvm_loppu;
        this.pvm_paivitetty = pvm_paivitetty;

        this.muistiinpanot = new ArrayList<Muistiinpano>();
        this.lapsiprojektit = new ArrayList<Projekti>();
    }

    /**
     * 
     * @param projekti
     */
    private Projekti(Projekti projekti) {
        this.id = projekti.getId();
        this.nimi = projekti.getNimi();
        this.esittely = projekti.getEsittely();
        this.arviointi = projekti.getArviointi();
        this.linkki = projekti.getLinkki();
        this.arvosana = projekti.getArvosana();
        this.arvosana_oma = projekti.getArvosana_oma();
        this.isa = projekti.getIsa();
        this.tila = projekti.getTila();
        this.asema = projekti.getAsema();
        this.pvm_alku = projekti.getPvm_alku();
        this.pvm_loppu = projekti.getPvm_loppu();
        this.pvm_paivitetty = projekti.getPvm_paivitetty();
        this.muistiinpanot = projekti.getMuistiinpanot();
        this.lapsiprojektit = projekti.getLapsiprojektit();
    }

    /**
     * Metodilla voidaan hakea käyttäjän projektit tietokannasta.
     *
     * @param kayttajaid Käyttäjän id-tunniste, joka omistaa projektit.
     * @return ArrayList, jossa löydetyt projektit.
     */
    public ArrayList<Projekti> selectProjektit(int kayttajaid) {
        Connection conn = null;
        ResultSet rs = null;
        PreparedStatement ps = null;

        ArrayList<Projekti> proj = new ArrayList<Projekti>();

        try {
            conn = new Tietokanta().getYhteys();

            ps = conn.prepareStatement("" +
                    "SELECT ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA FROM OPINTOPAIVAKIRJA.PROJEKTI " +
                    "WHERE KAYTTAJA_ID = ? ORDER BY PROJEKTI_ID, NIMI ASC");
            ps.setInt(1, kayttajaid);

            rs = ps.executeQuery();

            while (rs.next()) {
                Projekti p = new Projekti(rs.getInt("id"),
                        rs.getString("nimi"), rs.getString("esittely"),
                        rs.getString("arviointi"), rs.getString("linkki"),
                        rs.getInt("arvosana"), rs.getInt("arvosana_oma"),
                        rs.getInt("asema"), rs.getInt("projekti_id"),
                        rs.getDate("pvm_alku"), rs.getDate("pvm_loppu"),
                        rs.getTimestamp("pvm_paivitetty"), 1);

                // projektin muistiinpanot
                Muistiinpano m = new Muistiinpano();
                p.muistiinpanot.addAll(m.selectMuistiinpanot(p.getId()));

                proj.add(p);
            }

        } catch (SQLException ex) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
            proj = null;
        } catch (NullPointerException e) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), e);
            proj = null;
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                    ps = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }

            if (rs != null) {
                try {
                    rs.close();
                    rs = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }
            return proj;
        }
    }

    /**
     * Metodilla voidaan lisätä projekti tietokantaan.
     *
     * @param kayttajaid Muistiinpanon omistavan käyttäjän id-tunniste.
     * @return boolean siitä, onnistuiko muistiinpanon lisääminen tietokantaan.
     */
    public boolean insertProjekti(int kayttajaid) {
        Connection conn = null;
        PreparedStatement ps = null;

        if (!onkoProjekti(kayttajaid, this)) {

            boolean vastaus = true;

            try {
                conn = new Tietokanta().getYhteys();

                if (this.isa > 0) { // derbyssä joku käpy. tehtävä näin.
                    ps = conn.prepareStatement("" +
                            "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                            "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, " +
                            "ARVIOINTI, LINKKI, PVM_ALKU, PVM_LOPPU, " +
                            "PVM_PAIVITETTY, ARVOSANA, ARVOSANA_OMA, ASEMA) " +
                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, " +
                            "CURRENT_TIMESTAMP, ?, ?, ?)");

                    ps.setInt(1, kayttajaid);
                    ps.setInt(2, this.isa);
                    ps.setString(3, this.nimi);
                    ps.setString(4, this.esittely);
                    ps.setString(5, this.arviointi);
                    ps.setString(6, this.linkki);
                    ps.setDate(7, this.pvm_alku);
                    ps.setDate(8, this.pvm_loppu);
                    ps.setInt(9, this.arvosana);
                    ps.setInt(10, this.arvosana_oma);
                    ps.setInt(11, this.asema);
                } else { // isa = NULL
                    ps = conn.prepareStatement("" +
                            "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                            "(KAYTTAJA_ID, NIMI, ESITTELY, ARVIOINTI, " +
                            "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, " +
                            "ARVOSANA, ARVOSANA_OMA, ASEMA) " +
                            "VALUES (?, ?, ?, ?, ?, ?, ?, " +
                            "CURRENT_TIMESTAMP, ?, ?, ?)");

                    ps.setInt(1, kayttajaid);
                    ps.setString(2, this.nimi);
                    ps.setString(3, this.esittely);
                    ps.setString(4, this.arviointi);
                    ps.setString(5, this.linkki);
                    ps.setDate(6, this.pvm_alku);
                    ps.setDate(7, this.pvm_loppu);
                    ps.setInt(8, this.arvosana);
                    ps.setInt(9, this.arvosana_oma);
                    ps.setInt(10, this.asema);
                }

                ps.executeUpdate();

                // Muistiinpanot update (1), insert (0), delete (-1)
                for (Muistiinpano muistiinpano : muistiinpanot) {
                    if (muistiinpano.getTila() < 0) {
                        muistiinpano.deleteMuistiinpano();
                    } else if (muistiinpano.getTila() == 0) {
                        muistiinpano.insertMuistiinpano(kayttajaid, this.id, muistiinpano);
                    } else if (muistiinpano.getTila() > 0) {
                        muistiinpano.updateMuistiinpano();
                    }
                }

            } catch (SQLException ex) {
                Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                vastaus = false;
            } finally {
                if (ps != null) {
                    try {
                        ps.close();
                        ps = null;
                    } catch (SQLException ex) {
                        Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                    }
                }
                return vastaus;
            }
        }
        return false;
    }

    /**
     * Metodilla voidaan päivittää projektin tiedot tietokantaan.
     *
     * @param kayttajaid Projektin omistavan käyttäjän id-tunniste.
     * @return boolean siitä, onnistuiko projektin paivittaminen tietokannassa.
     */
    public boolean updateProjekti(int kayttajaid) {
        Connection conn = null;
        PreparedStatement ps = null;

        boolean vastaus = true;

        try {
            conn = new Tietokanta().getYhteys();

            // Pakko tehdä näin. derbyssä joku käpy projekti_id:n
            // kanssa -> integer- ja null-valuet.
            if (this.isa > 0) {
                ps = conn.prepareStatement("" +
                        "UPDATE OPINTOPAIVAKIRJA.PROJEKTI " +
                        "SET PROJEKTI_ID = ?, NIMI = ?, ESITTELY = ?, " +
                        "ARVIOINTI = ?, LINKKI = ?, PVM_ALKU = ?, " +
                        "PVM_LOPPU = ?, PVM_PAIVITETTY = CURRENT_TIMESTAMP, " +
                        "ARVOSANA = ?, ARVOSANA_OMA = ?, ASEMA = ? " +
                        "WHERE ID = ?");

                ps.setInt(1, this.isa);
                ps.setString(2, this.nimi);
                ps.setString(3, this.esittely);
                ps.setString(4, this.arviointi);
                ps.setString(5, this.linkki);
                ps.setDate(6, this.pvm_alku);
                ps.setDate(7, this.pvm_loppu);
                ps.setInt(8, this.arvosana);
                ps.setInt(9, this.arvosana_oma);
                ps.setInt(10, this.asema);
                ps.setInt(11, this.id);
            } else { // isa = NULL
                ps = conn.prepareStatement("" +
                        "UPDATE OPINTOPAIVAKIRJA.PROJEKTI " +
                        "SET NIMI = ?, ESITTELY = ?, ARVIOINTI = ?, " +
                        "LINKKI = ?, PVM_ALKU = ?, PVM_LOPPU = ?, " +
                        "PVM_PAIVITETTY = CURRENT_TIMESTAMP, ARVOSANA = ?, " +
                        "ARVOSANA_OMA = ?, ASEMA = ? WHERE ID = ?");

                ps.setString(1, this.nimi);
                ps.setString(2, this.esittely);
                ps.setString(3, this.arviointi);
                ps.setString(4, this.linkki);
                ps.setDate(5, this.pvm_alku);
                ps.setDate(6, this.pvm_loppu);
                ps.setInt(7, this.arvosana);
                ps.setInt(8, this.arvosana_oma);
                ps.setInt(9, this.asema);
                ps.setInt(10, this.id);
            }

            ps.executeUpdate();

            // Muistiinpanot update (1), insert (0), delete (-1)
            for (Muistiinpano muistiinpano : muistiinpanot) {
                if (muistiinpano.getTila() > 0) {
                    muistiinpano.updateMuistiinpano();
                } else if (muistiinpano.getTila() == 0) {
                    muistiinpano.insertMuistiinpano(kayttajaid, this.id, muistiinpano);
                } else if (muistiinpano.getTila() < 0) {
                    muistiinpano.deleteMuistiinpano();
                }
            }

        } catch (SQLException ex) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
            vastaus = false;
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                    ps = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }
            return vastaus;
        }
    }

    /**
     * Metodilla voidaan poistaa projekti tietokannasta.
     *
     * @return boolean siitä, onnistuiko projektin poistaminen tietokannasta
     */
    public boolean deleteProjekti() {
        Connection conn = null;
        PreparedStatement ps = null;

        boolean vastaus = true;

        try {
            conn = new Tietokanta().getYhteys();

            // Muistiinpanojen poistaminen hoidetaan Derbyssa triggerillä
            ps = conn.prepareStatement("" +
                    "DELETE FROM OPINTOPAIVAKIRJA.PROJEKTI WHERE ID = ?");
            ps.setInt(1, getId());

            ps.executeUpdate();

        } catch (SQLException ex) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
            vastaus = false;
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                    ps = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }
            return vastaus;
        }
    }

    /**
     * Metodilla voidaan tehdä tietokantaan valmiita esimääriteltyjä projektipohjia.
     * <p>
     * Valmiit projektitemplatet:
     * <ol>
     * <li>Yleistemplate, joka sisältää Yleismuistiinpanot ja Termipankki projektit.</li>
     * <li>DI-tutkinnon template.</li>
     * <li>MBA-tutkinnon template.</li>
     * <li>AMK-tutkinnon template.</li>
     * <li>2. asteen opintojen template.</li>
     * </ol>
     * 
     * @param kayttajaid Käyttäjän id-tunniste, joka omistaa tehtävät projektit.
     * @param template int, joka määrittää mikä template luodaan.
     */
    public void insertTemplate(int kayttajaid, int template) {
        Connection conn = null;

        ArrayList<String> lauseet = new ArrayList<String>();

        conn = new Tietokanta().getYhteys();

        Statement s = null;

        // Yleismuistiinpanot ja Termipankki
        if (template == 1) {

            String yleismuistiinpanot =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, " +
                    "ARVIOINTI, LINKKI, PVM_ALKU, PVM_LOPPU, " +
                    "PVM_PAIVITETTY, ARVOSANA, ARVOSANA_OMA, ASEMA) " +
                    "VALUES " +
                    "(" + kayttajaid + ", null, 'Yleismuistiinpanot', " +
                    "'Yleismuistiinpanot on tarkoitettu muistiinpanoille, " +
                    "jotka eivät kuulu minkään erityisen projektin tai " +
                    "tavoitteen alle.', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-07'), CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(yleismuistiinpanot);

//            String termipankki =
//                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI (KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, ARVOSANA_OMA, ASEMA) VALUES " +
//                    "(" + kayttajaid + ", null, 'Termipankki', 'Termipankki on tarkoitettu muistilistaksi / sanakirjaksi erilaisille termeille ja käsitteille.', '', '', CURRENT_DATE, DATE('2017-12-07'), CURRENT_TIMESTAMP, 0, 0, 0) ";
//            lauseet.add(termipankki);

        } else if (template == 2) { // DI-tutkinto

            String di =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", null, 'DI-tutkinto', " +
                    "'DI-tutkinto on kansainvälisesti tunnustettu " +
                    "arvostettu korkeakoulututkinto.', '', " +
                    "'http://www.tut.fi/pori', CURRENT_DATE, " +
                    "DATE('2017-12-07'), CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(di);

            String aineet =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Pääaine', 'DI-tutkinnon pääaineopinnot', '', " +
                    "'http://www.tut.fi/', CURRENT_DATE, DATE('2017-12-06'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Sivuaine', 'DI-tutkinnon sivuaineopinnot', '', " +
                    "'http://www.tut.fi/', CURRENT_DATE, " +
                    "DATE('2017-12-06'), CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Yleisopinnot', 'DI-tutkinnon yleis- ja " +
                    "vapaavalintaiset opinnot', '', 'http://www.tut.fi/', " +
                    "CURRENT_DATE, DATE('2017-12-06'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Täydentävät opinnot', 'DI-tutkinnon täydentävät " +
                    "opinnot insinööreille ja tradenomeille.', '', " +
                    "'http://www.tut.fi/', CURRENT_DATE, DATE('2017-12-06'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(aineet);

        } else if (template == 3) { // Yleiskurssi

            String yleinen_kurssi =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", null, 'Opinnot', " +
                    "'Opintojen alle voit lisätä uusia kursseja ja niihin " +
                    "muistiinpanoja.', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-07'), CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(yleinen_kurssi);

            String kurssi =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Kurssi 1', '', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-06'), CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(kurssi);

        } else if (template == 4) { // MBA

            String mba =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", null, " +
                    "'Master of Business Administration', '', '', '', " +
                    "CURRENT_DATE, DATE('2017-12-07'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(mba);

        } else if (template == 5) { // JOKO-koulutus

            String joko =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", null, 'JOKO-koulutus', '', '', '', " +
                    "CURRENT_DATE, DATE('2017-12-07'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(joko);

            String johtaminen =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Ihmisten johtaminen', '', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-07'), CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Strateginen johtaminen', '', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-07'), CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ", IDENTITY_VAL_LOCAL(), " +
                    "'Resurssien johtaminen', '', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-07'), CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(johtaminen);

            String ihmisten_johtaminen_ala =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", (SELECT P.ID " +
                    "FROM OPINTOPAIVAKIRJA.PROJEKTI P " +
                    "WHERE P.NIMI LIKE 'Ihmisten johtaminen' " +
                    "AND P.KAYTTAJA_ID = " + kayttajaid + "), " +
                    "'Johtajuus ja esimiestaidot', '', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-06'), CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ", (SELECT P.ID " +
                    "FROM OPINTOPAIVAKIRJA.PROJEKTI P " +
                    "WHERE P.NIMI LIKE 'Ihmisten johtaminen' " +
                    "AND P.KAYTTAJA_ID = " + kayttajaid + "), " +
                    "'Esimies viestijänä', '', '', '', CURRENT_DATE, " +
                    "DATE('2017-12-06'), CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(ihmisten_johtaminen_ala);

            String strateginen_johtaminen_ala =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ",  (SELECT P.ID " +
                    "FROM OPINTOPAIVAKIRJA.PROJEKTI P " +
                    "WHERE P.NIMI LIKE 'Strateginen johtaminen' " +
                    "AND P.KAYTTAJA_ID = " + kayttajaid + "), " +
                    "'Strateginen ajattelu ja strategiaprosessi', '', '', '', " +
                    "CURRENT_DATE, DATE('2017-12-06'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ",  (SELECT P.ID " +
                    "FROM OPINTOPAIVAKIRJA.PROJEKTI P " +
                    "WHERE P.NIMI LIKE 'Strateginen johtaminen' " +
                    "AND P.KAYTTAJA_ID = " + kayttajaid + "), " +
                    "'Yrityksen strateginen toimintaympäristö', '', '', '', " +
                    "CURRENT_DATE, DATE('2017-12-06'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(strateginen_johtaminen_ala);

            String resurssien_johtaminen_ala =
                    "INSERT INTO OPINTOPAIVAKIRJA.PROJEKTI " +
                    "(KAYTTAJA_ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, ARVOSANA, " +
                    "ARVOSANA_OMA, ASEMA) VALUES " +
                    "(" + kayttajaid + ", (SELECT P.ID " +
                    "FROM OPINTOPAIVAKIRJA.PROJEKTI P " +
                    "WHERE P.NIMI LIKE 'Resurssien johtaminen' " +
                    "AND P.KAYTTAJA_ID = " + kayttajaid + "), " +
                    "'Talouden suunnittelu ja ohjaus', '', '', '', " +
                    "CURRENT_DATE, DATE('2017-12-06'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0), " +
                    "(" + kayttajaid + ", (SELECT P.ID " +
                    "FROM OPINTOPAIVAKIRJA.PROJEKTI P " +
                    "WHERE P.NIMI LIKE 'Resurssien johtaminen' " +
                    "AND P.KAYTTAJA_ID = " + kayttajaid + "), " +
                    "'Liiketoimintatiedon ja osaamisen johtaminen', " +
                    "'', '', '', CURRENT_DATE, DATE('2017-12-06'), " +
                    "CURRENT_TIMESTAMP, 0, 0, 0) ";
            lauseet.add(resurssien_johtaminen_ala);

        }

        try {
            s = conn.createStatement();

            for (String lause : lauseet) {
                s.execute(lause);
            }

        } catch (SQLException ex) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
        }

        try {
            if (s != null) {
                s.close();
                s = null;
            }
        } catch (SQLException ex) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
        }

    }

    /**
     * Metodilla voidaan testata onko haettu projekti tietokannassa.
     *
     * @param kayttajaid Projektin omistavan käyttäjän id-tunniste.
     * @param projekti Projekti, jota etsitään tietokannasta.
     * @return boolean siitä, löytyikö haettu projekti tietokannnasta.
     */
    public boolean onkoProjekti(int kayttajaid, Projekti projekti) {
        Connection conn = null;
        ResultSet rs = null;
        PreparedStatement ps = null;

        boolean proj = false;

        try {
            conn = new Tietokanta().getYhteys();

            if (this.getIsa() == 0) {
                ps = conn.prepareStatement("" +
                        "SELECT COUNT(*) AS LKM " +
                        "FROM OPINTOPAIVAKIRJA.PROJEKTI " +
                        "WHERE NIMI = ? AND KAYTTAJA_ID = ?");
                ps.setString(1, projekti.getNimi());
                ps.setInt(2, kayttajaid);
            } else {
                ps = conn.prepareStatement("" +
                        "SELECT COUNT(*) AS LKM " +
                        "FROM OPINTOPAIVAKIRJA.PROJEKTI " +
                        "WHERE NIMI = ? AND KAYTTAJA_ID = ? " +
                        "AND PROJEKTI_ID = ?");
                ps.setString(1, projekti.getNimi());
                ps.setInt(2, kayttajaid);
                ps.setInt(3, projekti.getIsa());
            }

            rs = ps.executeQuery();

            int tmp = 0;

            while (rs.next()) {
                tmp = rs.getInt("lkm");
            }

            if (tmp > 0) {
                proj = true;
            }

        } catch (SQLException ex) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
            proj = false;
        } catch (NullPointerException e) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), e);
            proj = false;
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                    ps = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }

            if (rs != null) {
                try {
                    rs.close();
                    rs = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }
            return proj;
        }
    }

    /**
     * Metodilla voidaan hakea 5 viimeisintä käyttäjän projektia.
     *
     * @param kayttajaid Projektin omistavan käyttäjän id-tunniste.
     * @return totuusarvo siitä, onnistuiko projektien hakeminen.
     */
    public ArrayList<Projekti> selectTop5Projektit(int kayttajaid) {
        Connection conn = null;
        ResultSet rs = null;
        PreparedStatement ps = null;

        ArrayList<Projekti> projektit = new ArrayList<Projekti>();
        ArrayList<Projekti> proj = new ArrayList<Projekti>();

        try {
            conn = new Tietokanta().getYhteys();

            ps = conn.prepareStatement("" +
                    "SELECT ID, PROJEKTI_ID, NIMI, ESITTELY, ARVIOINTI, " +
                    "LINKKI, PVM_ALKU, PVM_LOPPU, PVM_PAIVITETTY, " +
                    "ARVOSANA, ARVOSANA_OMA, ASEMA " +
                    "FROM OPINTOPAIVAKIRJA.PROJEKTI " +
                    "WHERE KAYTTAJA_ID = ? " +
                    "ORDER BY PVM_PAIVITETTY DESC");
            ps.setInt(1, kayttajaid);

            rs = ps.executeQuery();

            while (rs.next()) {
                Projekti p = new Projekti(rs.getInt("id"),
                        rs.getString("nimi"), rs.getString("esittely"),
                        rs.getString("arviointi"), rs.getString("linkki"),
                        rs.getInt("arvosana"), rs.getInt("arvosana_oma"),
                        rs.getInt("asema"), rs.getInt("Projekti_id"),
                        rs.getDate("pvm_alku"), rs.getDate("pvm_loppu"),
                        rs.getTimestamp("pvm_paivitetty"), 1);

                proj.add(p);
            }

        } catch (SQLException ex) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
            proj = null;
        } catch (NullPointerException e) {
            Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), e);
            proj = null;
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                    ps = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }

            if (rs != null) {
                try {
                    rs.close();
                    rs = null;
                } catch (SQLException ex) {
                    Virheenkasittely.getInstance().setVirhe(Tietokanta.class.getName(), ex);
                }
            }

            int lukumaara = (proj.size() > 4) ? 5 : proj.size();
            for (int i = 0; i < lukumaara; ++i) {
                projektit.add(proj.get(i));
            }

            return projektit;
        }
    }

    /**
     * Metodi järjestää projektit-taulukon hierarkisiin
     * taulukoihin -> Projektilla on aliprojekteja.
     * 
     * @param projektit Projektit, jotka järjestetään hierarkiaan.
     * @return ArrayList, jossa projektit hierarkiaan järjestettyinä.
     */
    public ArrayList<Projekti> jarjestaProjektit(ArrayList<Projekti> projektit) {
        /*
         * Tämä pitäisi toteuttaa paremmin.
         * Nyt 5 tasoa on maksimi.
         */

        ArrayList<Projekti> nodet = new ArrayList<Projekti>();
        ArrayList<Integer> paikat = new ArrayList<Integer>();

        // 1. tason projektit
        if (!projektit.isEmpty()) {
            for (int i = 0; i < projektit.size(); ++i) {
                if (projektit.get(i).getIsa() == 0) {
                    nodet.add(projektit.get(i));
                    paikat.add(i);
                }
            }
        }

        for (Integer integer : paikat) {
            projektit.remove(integer);
        }
        paikat.clear();
        projektit.trimToSize();

        // 2. tason projektit
        if (!projektit.isEmpty()) {
            for (int i = 0; i < projektit.size(); ++i) {
                for (int j = 0; j < nodet.size(); ++j) {

                    if (projektit.get(i).getIsa() == nodet.get(j).getId()) {
                        nodet.get(j).lapsiprojektit.add(projektit.get(i));
                        paikat.add(i);
                    }
                }
            }
        }

        for (Integer integer : paikat) {
            projektit.remove(integer);
        }
        paikat.clear();
        projektit.trimToSize();

        // 3. tason projektit
        if (!projektit.isEmpty()) {
            for (int i = 0; i < projektit.size(); ++i) {
                for (int j = 0; j < nodet.size(); ++j) {
                    for (int k = 0; k < nodet.get(j).lapsiprojektit.size(); ++k) {
                        if (projektit.get(i).getIsa() == nodet.get(j).lapsiprojektit.get(k).getId()) {
                            nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.add(projektit.get(i));
                            paikat.add(i);
                        }
                    }
                }
            }
        }

        for (Integer integer : paikat) {
            projektit.remove(integer);
        }
        paikat.clear();
        projektit.trimToSize();

        // 4. tason projektit
        if (!projektit.isEmpty()) {
            for (int i = 0; i < projektit.size(); ++i) {
                for (int j = 0; j < nodet.size(); ++j) {
                    for (int k = 0; k < nodet.get(j).lapsiprojektit.size(); ++k) {
                        for (int m = 0; m < nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.size(); ++m) {
                            if (projektit.get(i).getIsa() == nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.get(m).getId()) {
                                nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.get(m).lapsiprojektit.add(projektit.get(i));
                                paikat.add(i);
                            }
                        }
                    }
                }
            }
        }

        for (Integer integer : paikat) {
            projektit.remove(integer);
        }
        paikat.clear();
        projektit.trimToSize();

        // 5. tason projektit
        if (!projektit.isEmpty()) {
            for (int i = 0; i < projektit.size(); ++i) {
                for (int j = 0; j < nodet.size(); ++j) {
                    for (int k = 0; k < nodet.get(j).lapsiprojektit.size(); ++k) {
                        for (int m = 0; m < nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.size(); ++m) {
                            for (int n = 0; n < nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.get(m).lapsiprojektit.size(); ++n) {
                                if (projektit.get(i).getIsa() == nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.get(m).lapsiprojektit.get(n).getId()) {
                                    nodet.get(j).lapsiprojektit.get(k).lapsiprojektit.get(m).lapsiprojektit.get(n).lapsiprojektit.add(projektit.get(i));
                                    paikat.add(i);
                                }
                            }
                        }
                    }
                }
            }
        }

        paikat.clear();
        projektit.clear();

        return nodet;
    }

    /**
     * Metodilla voidaan asettaa muistiinpano-olio projektin muistiinpanot taulukkoon.
     *
     * @param muistiinpano Muistiinpano, joka lisätään taulukkoon.
     */
    public void setMuistiinpano(Muistiinpano muistiinpano) {
        this.muistiinpanot.add(muistiinpano);
    }

    /**
     * @return the arvosana
     */
    public int getArvosana() {
        return arvosana;
    }

    /**
     * @param arvosana the arvosana to set
     */
    public void setArvosana(int arvosana) {
        this.arvosana = arvosana;
    }

    /**
     * @return the arvosana_oma
     */
    public int getArvosana_oma() {
        return arvosana_oma;
    }

    /**
     * @param arvosana_oma the arvosana_oma to set
     */
    public void setArvosana_oma(int arvosana_oma) {
        this.arvosana_oma = arvosana_oma;
    }

    /**
     * @return the esittely
     */
    public String getEsittely() {
        return esittely;
    }

    /**
     * @param esittely the esittely to set
     */
    public void setEsittely(String esittely) {
        this.esittely = esittely;
    }

    /**
     * @return the id
     */
    public int getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * @return the isa
     */
    public int getIsa() {
        return isa;
    }

    /**
     * @param isa the isa to set
     */
    public void setIsa(int isa) {
        this.isa = isa;
    }

    /**
     * @return the lapsiprojektit
     */
    public ArrayList<Projekti> getLapsiprojektit() {
        return lapsiprojektit;
    }

    /**
     * @param lapsiprojektit the lapsiprojektit to set
     */
    public void setLapsiprojektit(ArrayList<Projekti> lapsiprojektit) {
        this.lapsiprojektit = lapsiprojektit;
    }

    /**
     * @return the muistiinpanot
     */
    public ArrayList<Muistiinpano> getMuistiinpanot() {
        return muistiinpanot;
    }

    /**
     * @param muistiinpanot the muistiinpanot to set
     */
    public void setMuistiinpanot(ArrayList<Muistiinpano> muistiinpanot) {
        this.muistiinpanot = muistiinpanot;
    }

    /**
     * @return the nimi
     */
    public String getNimi() {
        return nimi;
    }

    /**
     * @param nimi the nimi to set
     */
    public void setNimi(String nimi) {
        this.nimi = nimi;
    }

    /**
     * @return the pvm_alku
     */
    public Date getPvm_alku() {
        return pvm_alku;
    }

    /**
     * @param pvm_alku the pvm_alku to set
     */
    public void setPvm_alku(Date pvm_alku) {
        this.pvm_alku = pvm_alku;
    }

    /**
     * @return the pvm_loppu
     */
    public Date getPvm_loppu() {
        return pvm_loppu;
    }

    /**
     * @param pvm_loppu the pvm_loppu to set
     */
    public void setPvm_loppu(Date pvm_loppu) {
        this.pvm_loppu = pvm_loppu;
    }

    /**
     * @return the paivitetty
     */
    public Timestamp getPvm_paivitetty() {
        return pvm_paivitetty;
    }

    /**
     * @param pvm_paivitetty the pvm_paivitetty to set
     */
    public void setPvm_paivitetty(Timestamp pvm_paivitetty) {
        this.pvm_paivitetty = pvm_paivitetty;
    }

    /**
     * @return the tila
     */
    public int getTila() {
        return tila;
    }

    /**
     * @param tila the tila to set
     */
    public void setTila(int tila) {
        this.tila = tila;
    }

    /**
     * @return the asema
     */
    public int getAsema() {
        return asema;
    }

    /**
     * @param asema the asema to set
     */
    public void setAsema(int asema) {
        this.asema = asema;
    }

    /**
     * @return the linkki
     */
    public String getLinkki() {
        return linkki;
    }

    /**
     * @param linkki the linkki to set
     */
    public void setLinkki(String linkki) {
        this.linkki = linkki;
    }

    /**
     * @return the arviointi
     */
    public String getArviointi() {
        return arviointi;
    }

    /**
     * @param arviointi the arviointi to set
     */
    public void setArviointi(String arviointi) {
        this.arviointi = arviointi;
    }
}
